package com.springboot.distributed.transaction;

import java.lang.reflect.Method;
import java.util.List;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.support.DefaultTransactionStatus;

import com.alibaba.dubbo.rpc.RpcContext;
import com.springboot.common.util.StringUtil;
import com.springboot.distributed.constant.TransactionConstants;
import com.springboot.distributed.transaction.annotation.GlobalDistributedTransaction;
import com.springboot.distributed.transaction.util.DistributedTransactionManager;

/**
 * 分布式事务处理器
 *
 * @author supu
 * @date 2019-09-05 17:43
 **/
public class DistributedTransactionHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(DistributedTransactionHandler.class);

    /**
     * 方法是否有 @GlobalDistributedTransaction 注解
     *
     * @param method
     * @return
     */
    public boolean isGlobalDistributedTransactionAnnotated(Method method) {
        if (method.isAnnotationPresent(GlobalDistributedTransaction.class)) {
            LOGGER.info("{} isGlobalDistributedTransactionAnnotated is true", methodInfo(method));
            return true;
        }
        return false;
    }

    /**
     * 注册分布式事务
     *
     * @return
     */
    public boolean registerDistributedTransaction() {
        String uniqueKey = getRpcDistributedTransactionUniqueKey();
        boolean isHeader = false;
        if (StringUtil.isEmpty(uniqueKey)) {
            // 事务入口处
            isHeader = true;
            uniqueKey = UUID.randomUUID().toString().replace("-", "");
        }

        DistributedTransactionManager.registerTransactionInfo(uniqueKey, isHeader);

        return true;
    }

    private String getRpcDistributedTransactionUniqueKey(){
        return RpcContext.getContext().getAttachment(TransactionConstants.UNIQUE_KEY);
    }

    /**
     * 是否是分布式事务
     *
     * @return
     */
    public boolean isDistributedTransaction() {
        return DistributedTransactionManager.hasRegisteredDistributedTransaction();
    }

    private String methodInfo(Method method) {
        return method.getDeclaringClass() + "." + method.getName();
    }

    /**
     * 完成之后清除操作
     */
    public void doCleanupAfterCompletion() {
        DistributedTransactionManager.clear();
    }

    /**
     * 保存事务状态并返回是否是事务入口
     *
     * @param transactionStatus
     * @return
     */
    public boolean saveTransactionStatus(DefaultTransactionStatus transactionStatus) {
        return DistributedTransactionManager.saveTransactionStatus(transactionStatus);
    }

    /**
     * 根据key获取事务状态列表
     *
     * @param uniqueKey
     * @return
     */
    public List<DefaultTransactionStatus> getDefaultTransactionStatusList(String uniqueKey) {
        return DistributedTransactionManager.getDefaultTransactionStatusList(uniqueKey);
    }

    /**
     * 根据key清除对应的事务状态列表
     *
     * @param uniqueKey
     */
    public void clearDistributedTransaction(String uniqueKey) {
        DistributedTransactionManager.clearDistributedTransaction(uniqueKey);
    }

    public String getUniqueKey(){
        return DistributedTransactionManager.getUniqueKey();
    }
}
